home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / base / net-tool.32- / net-tool / net-tools-1.32-alpha / netstat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  34.8 KB  |  1,449 lines

  1. /*
  2.  * netstat    This file contains an implementation of the command
  3.  *        that helps in debugging the networking modules.
  4.  *
  5.  * NET-TOOLS    A collection of programs that form the base set of the
  6.  *        NET-3 Networking Distribution for the LINUX operating
  7.  *        system.
  8.  *
  9.  * Version:    netstat 1.19 (1996-05-17)
  10.  *
  11.  * Authors:    Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
  12.  *        Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  13.  *        Phil Packer, <pep@wicked.demon.co.uk>
  14.  *        Johannes Stille, <johannes@titan.os.open.de>
  15.  *        Bernd Eckenfels, <net-tools@lina.inka.de>
  16.  *
  17.  * Tuned for NET3 by:
  18.  *        Alan Cox, <A.Cox@swansea.ac.uk>
  19.  *
  20.  *        Copyright (c) 1993  Fred Baumgarten
  21.  *
  22.  * Modified:
  23.  *
  24.  *960116 {1.01} Bernd Eckenfels:    verbose, cleanups
  25.  *960204 {1.10} Bernd Eckenfels:    aftrans, usage, new route_info, 
  26.  *                    DLFT_AF
  27.  *960204 {1.11} Bernd Eckenfels:    netlink support
  28.  *960204 {1.12} Bernd Eckenfels:    route_init()
  29.  *960215 {1.13} Bernd Eckenfels:    netlink_print honors HAVE_
  30.  *960217 {1.14} Bernd Eckenfels:    masq_info from Jos Vos and 
  31.  *                    ax25_info from Jonathan Naylor.
  32.  *960218 {1.15} Bernd Eckenfels:    ipx_info rewritten, -e for tcp/ipx
  33.  *960220 {1.16} Bernd Eckenfels:    minor output reformats, -a for -x
  34.  *960221 {1.17} Bernd Eckenfels:    route_init->getroute_init
  35.  *960426 {1.18} Bernd Eckenfels:    new RTACTION, SYM/NUM, FIB/CACHE
  36.  *960517 {1.19} Bernd Eckenfels:    usage() spelling fix and --unix inode, 
  37.  *                    ':' is part of sock_addr for --inet
  38.  *
  39.  *        This program is free software; you can redistribute it
  40.  *        and/or  modify it under  the terms of  the GNU General
  41.  *        Public  License as  published  by  the  Free  Software
  42.  *        Foundation;  either  version 2 of the License, or  (at
  43.  *        your option) any later version.
  44.  *
  45.  */
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include <strings.h>
  49. #include <unistd.h>
  50. #include <ctype.h>
  51. #include <fcntl.h>
  52. #include <netdb.h>
  53. #include <paths.h>
  54. #include <pwd.h>
  55. #include <getopt.h>
  56. #include <sys/param.h>
  57. #include <sys/socket.h>
  58. #include <linux/route.h>
  59. #include <netinet/in.h>
  60. #include <linux/if_ether.h>
  61. #include <linux/net.h>
  62. #include <linux/tcp.h>
  63. #include <sys/ioctl.h>
  64. #include <linux/ip.h>
  65. #include <linux/icmp.h>
  66. #include <linux/tcp.h>
  67. #include <linux/udp.h>
  68. #include <linux/if.h>
  69. #include <linux/ip_fw.h>
  70. #include "net-support.h"
  71. #include "pathnames.h"
  72. #include "version.h"
  73. #include "config.h"
  74. #include "net-locale.h"
  75.  
  76. #define DFLT_AF "inet"
  77.  
  78. #define FEATURE_NETSTAT
  79. #include "lib/net-features.h"
  80.  
  81. char *Release   = RELEASE,
  82.      *Version   = "netstat 1.19 (1996-05-17)",
  83.      *Signature = "Fred Baumgarten <dc6iq@insu1.etec.uni-karlsruhe.de> and Alan Cox.";
  84.  
  85.  
  86. #define E_READ  -1
  87. #define E_IOCTL -3
  88.  
  89.  
  90. struct interface {
  91.   char name[IFNAMSIZ];        /* interface name       */
  92.   short flags;                  /* various flags        */
  93.   int metric;            /* routing metric       */
  94.   int mtu;            /* MTU value            */
  95.   struct sockaddr addr;        /* IP address           */
  96.   struct sockaddr dstaddr;    /* P-P IP address       */
  97.   struct sockaddr broadaddr;    /* IP broadcast address */
  98.   struct sockaddr netmask;    /* IP network mask      */
  99.   struct sockaddr hwaddr;    /* HW address           */
  100.   struct enet_statistics stats;    /* statistics           */
  101. };
  102.  
  103. int flag_nlp = 0;
  104. int flag_int = 0;
  105. int flag_rou = 0;
  106. int flag_mas = 0;
  107.  
  108. int flag_all = 0;
  109. int flag_cnt = 0;
  110. int flag_deb = 0;
  111. int flag_not = 0;
  112. int flag_cf  = 0;
  113. int flag_opt = 0;
  114. int flag_raw = 0;
  115. int flag_tcp = 0;
  116. int flag_udp = 0;
  117. int flag_rom = 0;
  118. int flag_exp = 1;
  119. int flag_arg = 0;
  120. int flag_ver = 0;
  121.  
  122. int skfd;
  123. FILE *procinfo;
  124. char *line[2000];
  125.  
  126. #if HAVE_RT_NETLINK
  127. static int
  128. netlink_print(void)
  129. {
  130.   int flag;
  131. #define NL_DEV   1
  132. #define NL_ADDR  2
  133. #define NL_MISC  4
  134.   int fd,ret;
  135.   struct netlink_rtinfo buf;
  136.   struct aftype *ap;
  137.   struct sockaddr *s;
  138.   
  139.   if ((fd = open(_PATH_DEV_ROUTE, O_RDONLY))<0) {
  140.     if (errno == ENODEV)    
  141.         ESYSNOT("netstat","/dev/route");
  142.     else
  143.         perror(_PATH_DEV_ROUTE);
  144.     return(-1);
  145.   }
  146.  
  147.   if (flag_ver) {
  148.       printf(NLS_CATGETS(catfd, netstatSet, netstat_nlp_title, "Netlink Kernel Messages"));
  149.       if (flag_cnt)
  150.           printf(NLS_CATGETS(catfd, netstatSet, netstat_nlp_cnt, " (continous)"));
  151.     printf("\n");      
  152.   }      
  153.       
  154.   do {
  155.     if ((ret=read(fd,(char *)&buf,sizeof(buf))) < 0) {
  156.             perror("read "_PATH_DEV_ROUTE);
  157.             return(-1);
  158.         }
  159.     if (ret != sizeof(buf)) {
  160.         EINTERN("netstat.c","netlink message size mismatch");
  161.         return(-1);
  162.     }
  163.     
  164.     flag=0;
  165.     /* No NLS, keep this parseable */
  166.     switch(buf.rtmsg_type) {
  167.          case RTMSG_NEWROUTE:
  168.             printf("NEWROUTE\t");
  169.             flag=NL_DEV|NL_ADDR|NL_MISC;
  170.             break;
  171.             case RTMSG_DELROUTE:
  172.                 printf("DELROUTE\t");
  173.             flag=NL_DEV|NL_ADDR|NL_MISC;
  174.                 break;
  175.             case RTMSG_NEWDEVICE:
  176.                 printf("NEWDEVICE\t");
  177.             flag=NL_DEV|NL_MISC;
  178.                 break;
  179.             case RTMSG_DELDEVICE:
  180.                 printf("DELDEVICE\t");
  181.                 flag=NL_DEV|NL_MISC;
  182.                 break;
  183.             default:
  184.                 printf("UNKNOWN%lx\t",buf.rtmsg_type);
  185.                 flag=NL_DEV|NL_ADDR|NL_MISC;
  186.             break;
  187.     }
  188.  
  189.     if (flag&NL_ADDR) {
  190.         s=&buf.rtmsg_dst;
  191.         ap = get_afntype(s->sa_family);
  192.         if (ap == NULL) ap = get_afntype(0);
  193.  
  194.         printf("%s/%s ",ap->sprint(s, flag_not), ap->name);
  195.  
  196.         s=&buf.rtmsg_gateway;
  197.         ap = get_afntype(s->sa_family);
  198.         if (ap == NULL) ap = get_afntype(0);
  199.  
  200.         printf("%s/%s ",ap->sprint(s, flag_not), ap->name);
  201.  
  202.         s=&buf.rtmsg_genmask;
  203.         ap = get_afntype(s->sa_family);
  204.         if (ap == NULL) ap = get_afntype(0);
  205.  
  206.         printf("%s/%s ",ap->sprint(s, 1), ap->name);
  207.     }
  208.     if (flag&NL_MISC) {
  209.             printf("0x%x %d ",buf.rtmsg_flags,buf.rtmsg_metric);
  210.     }
  211.     if (flag&NL_DEV) {
  212.     printf("%s",buf.rtmsg_device);
  213.     }
  214.     printf("\n");
  215.   } while(flag_cnt);
  216.   close(fd);
  217.   return(0);
  218. }
  219. #endif
  220.  
  221.  
  222.  
  223. #if HAVE_AFNETROM
  224. static int netrom_info(void)
  225. {
  226.     FILE *f;
  227.     char buffer[256],dev[16];
  228.     int st,vs,vr,sendq,recvq;
  229.     static char *netrom_state[4]=
  230.     {
  231.         "LISTENING",
  232.         "CONN SENT",
  233.         "DISC SENT",
  234.         "ESTABLISHED"
  235.     };
  236.  
  237.     if(!(f=fopen(_PATH_PROCNET_NR, "r")))
  238.     {
  239.         if (errno != ENOENT) {
  240.             perror(_PATH_PROCNET_NR);
  241.             return(-1);
  242.         }
  243.         if (flag_arg || flag_ver)
  244.             ESYSNOT("netstat","AF NETROM");
  245.         if (flag_arg)
  246.             return(1);
  247.         else
  248.             return(0);
  249.     }
  250.     printf(NLS_CATGETS(catfd, netstatSet, netstat_netrom, "Activate NET/ROM sockets\n"));
  251.     printf(NLS_CATGETS(catfd, netstatSet, netstat_header_netrom, "User       Dest       Source     Device  State        Vr/Vs  Send-Q  Recv-Q\n"));
  252.     fgets(buffer,256,f);
  253.     while(fgets(buffer,256,f))
  254.     {
  255.         buffer[9]=0;
  256.         buffer[19]=0;
  257.         buffer[29]=0;
  258.         sscanf(buffer+30,"%s %*d/%*d %*d/%*d %d %d %d %*d %*d/%*d %*d/%*d %*d/%*d %*d %*d %d %d",
  259.             dev,&st,&vs,&vr,&sendq,&recvq);
  260.         printf("%-9s  %-9s  %-9s  %-6s  %-11s  %02d/%02d  %-6d  %-6d\n",
  261.             buffer,buffer+10,buffer+20,
  262.             dev,
  263.             netrom_state[st],
  264.             vr,vs,sendq,recvq);
  265.     }
  266.     fclose(f);
  267.     return 0;        
  268. }
  269. #endif
  270.  
  271.  
  272. #if HAVE_AFINET
  273.  
  274.  
  275. static int
  276. tcp_info(void)
  277. {
  278.   char buffer[8192], local_addr[128];
  279.   char rem_addr[128], *tcp_state, timers[64];
  280.   struct sockaddr_in localaddr, remaddr;
  281.   struct aftype *ap;
  282.   unsigned long rxq, txq, time_len, retr;
  283.   int num, local_port, rem_port, d, state;
  284.   int uid, timer_run, lnr = 0;
  285.   struct passwd *pw;
  286.   
  287.   if ((procinfo = fopen(_PATH_PROCNET_TCP, "r")) == NULL) {
  288.     if (errno != ENOENT) {
  289.         perror(_PATH_PROCNET_TCP);
  290.         return(-1);
  291.     }
  292.     if (flag_arg || flag_ver)
  293.         ESYSNOT("netstat","AF INET (tcp)");
  294.     if (flag_arg)
  295.         return(1);
  296.     else
  297.         return(0);
  298.   }
  299.  
  300.   fgets(buffer, sizeof(buffer), procinfo);
  301.   while (! feof(procinfo)) {
  302.     fgets(buffer, sizeof(buffer), procinfo);
  303.     num = strlen(buffer)+1;
  304.     if ((line[lnr] = (char *)malloc(num)) != NULL) {
  305.         strcpy(line[lnr++], buffer);
  306.         if (flag_deb) fprintf(stderr, "%s", buffer);
  307.     }
  308.   }
  309.   (void) fclose(procinfo);
  310.   lnr--; lnr--;
  311.   while (lnr >= 0) {
  312.     num = sscanf(line[lnr--],
  313.         "%d: %lX:%X %lX:%X %X %lX:%lX %X:%lX %lX %d\n",
  314.         &d, (unsigned long*)&localaddr.sin_addr.s_addr, &local_port,
  315.         (unsigned long*)&remaddr.sin_addr.s_addr, &rem_port, &state,
  316.         &txq, &rxq, &timer_run, &time_len, &retr, &uid);
  317.     if (flag_deb) fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_args,
  318.                           "%s -> %d args"), line[lnr+1], num);
  319.     if (num < 11) continue;        /* 13 ? */
  320.     localaddr.sin_family = AF_INET;
  321.     remaddr.sin_family = AF_INET;
  322.     if ((ap = get_afntype(localaddr.sin_family)) == NULL) {
  323.         fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_netstat,
  324.                         "netstat: unsupported address family %d !\n"),
  325.             localaddr.sin_family);
  326.         continue;
  327.     }
  328.     switch (state) {
  329.         case TCP_ESTABLISHED:
  330.             tcp_state = "ESTABLISHED";
  331.             break;
  332.  
  333.         case TCP_SYN_SENT:
  334.             tcp_state = "SYN_SENT";
  335.             break;
  336.  
  337.         case TCP_SYN_RECV:
  338.             tcp_state = "SYN_RECV";
  339.             break;
  340.  
  341.         case TCP_FIN_WAIT1:
  342.             tcp_state = "FIN_WAIT1";
  343.             break;
  344.  
  345.         case TCP_FIN_WAIT2:
  346.             tcp_state = "FIN_WAIT2";
  347.             break;
  348.  
  349.         case TCP_TIME_WAIT:
  350.             tcp_state = "TIME_WAIT";
  351.             break;
  352.  
  353.         case TCP_CLOSE:
  354.             tcp_state = "CLOSE";
  355.             break;
  356.  
  357.         case TCP_CLOSING:
  358.             tcp_state = "CLOSING";
  359.             break;
  360.  
  361.         case TCP_CLOSE_WAIT:
  362.             tcp_state = "CLOSE_WAIT";
  363.             break;
  364.  
  365.         case TCP_LAST_ACK:
  366.             tcp_state = "LAST_ACK";
  367.             break;
  368.  
  369.         case TCP_LISTEN:
  370.             tcp_state = "LISTEN";
  371.             time_len = 0;
  372.             retr = 0L;
  373.             rxq=0L;
  374.             txq=0L;
  375.             break;
  376.  
  377.         default:
  378.             tcp_state = "UNKNOWN";
  379.             break;
  380.     }
  381.     strcpy(local_addr, ap->sprint((struct sockaddr *)&localaddr, flag_not));
  382.     strcpy(rem_addr, ap->sprint((struct sockaddr *)&remaddr, flag_not));
  383.     if (flag_all || rem_port) {
  384.         sprintf(buffer, "%s", get_sname(htons(local_port), "tcp", flag_not));
  385.         if ((strlen(local_addr) + strlen(buffer)) > 22) {
  386.             local_addr[22-strlen(buffer)] = '\0';
  387.         }
  388.         strcat(local_addr, ":");
  389.         strcat(local_addr, buffer);
  390.         sprintf(buffer, "%s",get_sname(htons(rem_port), "tcp", flag_not));
  391.         if ((strlen(rem_addr) + strlen(buffer)) > 22) {
  392.             rem_addr[22-strlen(buffer)] = '\0';
  393.         }
  394.         strcat(rem_addr, ":");
  395.         strcat(rem_addr, buffer);
  396.         timers[0] = '\0';
  397.         if (flag_opt) switch (timer_run) {
  398.             case 0:
  399.                 sprintf(timers, NLS_CATGETS(catfd, netstatSet, netstat_off,
  400.                                 "off (0.00/%ld)"), retr);
  401.                       break;
  402.  
  403.             case 1:
  404.                 sprintf(timers, NLS_CATGETS(catfd, netstatSet, netstat_on,
  405.                                 "on (%2.2f/%ld)"),
  406.                     (double)time_len / 100, retr);
  407.                 break;
  408.  
  409.             default:
  410.                 sprintf(timers, NLS_CATGETS(catfd, netstatSet, netstat_unkn,
  411.                                 "unkn-%d (%2.2f/%ld)"),
  412.                     timer_run, (double)time_len / 100, retr);
  413.                 break;
  414.         }
  415.         printf("tcp   %6ld %6ld %-23s %-23s %-12s",
  416.             rxq, txq, local_addr, rem_addr, tcp_state);
  417.  
  418.         if (flag_exp > 1) {
  419.             if (!flag_not && ((pw = getpwuid(uid)) != NULL))
  420.                 printf("%-10s ", pw->pw_name);
  421.             else
  422.                 printf("%-10d ",uid);
  423.         }
  424.  
  425.         if (flag_opt) printf("%s", timers);
  426.         printf("\n");
  427.     }
  428.   }
  429.   return(0);
  430. }
  431.  
  432.  
  433. static int
  434. udp_info(void)
  435. {
  436.   char buffer[8192], local_addr[64], rem_addr[64];
  437.   char *udp_state, timer_queued, timers[64], more[512];
  438.   int num, local_port, rem_port, d, state, timer_run, lnr = 0;
  439.   struct sockaddr_in localaddr, remaddr;
  440.   struct aftype *ap;
  441.   unsigned long rxq, txq, time_len, retr;
  442.   
  443.   if ((procinfo = fopen(_PATH_PROCNET_UDP, "r")) == NULL) {
  444.     if (errno != ENOENT) {
  445.         perror(_PATH_PROCNET_UDP);
  446.         return(-1);
  447.     }
  448.     if (flag_arg || flag_ver)
  449.         ESYSNOT("netstat","AF INET (udp)");
  450.     if (flag_arg)
  451.         return(1);
  452.     else
  453.         return(0);
  454.   }
  455.  
  456.   fgets(buffer, sizeof(buffer), procinfo);
  457.   while (! feof(procinfo)) {
  458.     fgets(buffer, sizeof(buffer), procinfo);
  459.     if ((line[lnr] = (char *)malloc(strlen(buffer)+1)) != NULL) {
  460.         strcpy(line[lnr++], buffer);
  461.         if (flag_deb) fprintf(stderr, "%s", buffer);
  462.     }
  463.   }
  464.   (void) fclose(procinfo);
  465.   lnr--; lnr--;
  466.  
  467.   while (lnr >= 0) {
  468.     more[0] = '\0';
  469.     timer_queued = '\0';
  470.     num = sscanf(line[lnr--],
  471.         "%d: %lX:%X %lX:%X %X %lX:%lX %X:%lX %lX %c %s\n",
  472.         &d, (unsigned long*)&localaddr.sin_addr.s_addr, &local_port,
  473.         (unsigned long*)&remaddr.sin_addr.s_addr, &rem_port, &state,
  474.         &txq, &rxq, &timer_run, &time_len, &retr,
  475.         &timer_queued, more);
  476.     localaddr.sin_family = AF_INET;
  477.     remaddr.sin_family = AF_INET;
  478.     if ((ap = get_afntype(localaddr.sin_family)) == NULL) {
  479.         fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_netstat,
  480.                         "netstat: unsupported address family %d !\n"),
  481.             localaddr.sin_family);
  482.         continue;
  483.     }
  484.  
  485.     retr = 0L;
  486.     if (! flag_opt) more[0] = '\0';
  487.     if (flag_deb) fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_args, "%s -> %d args"), line[lnr+1], num);
  488.     if (num < 10) continue;
  489.  
  490.     switch (state) {
  491.         case TCP_ESTABLISHED:
  492.             udp_state = "ESTABLISHED";
  493.             break;
  494.  
  495.         case TCP_CLOSE:
  496.             udp_state = "";
  497.             break;
  498.             
  499.         default:
  500.             udp_state = "UNKNOWN";
  501.             break;
  502.     }
  503.  
  504.     strcpy(local_addr, ap->sprint((struct sockaddr *)&localaddr, flag_not));
  505.     strcpy(rem_addr, ap->sprint((struct sockaddr *)&remaddr, flag_not));
  506.     if (flag_all || localaddr.sin_addr.s_addr) {
  507.         sprintf(buffer, "%s", get_sname(htons(local_port), "udp", flag_not));
  508.         if ((strlen(local_addr) + strlen(buffer)) > 22) {
  509.             local_addr[22-strlen(buffer)] = '\0';
  510.         }
  511.         strcat(local_addr, ":");
  512.         strcat(local_addr, buffer);
  513.         sprintf(buffer, "%s", get_sname(htons(rem_port), "udp", flag_not));
  514.         if ((strlen(rem_addr) + strlen(buffer)) > 22) {
  515.             rem_addr[22-strlen(buffer)] = '\0';
  516.         }
  517.         strcat(rem_addr, ":");
  518.         strcat(rem_addr, buffer);
  519.  
  520.         timers[0] = '\0';
  521.         if (flag_opt) switch (timer_run) {
  522.             case 0:
  523.                 sprintf(timers, NLS_CATGETS(catfd, netstatSet, netstat_off2,
  524.                                 "off (0.00/%ld) %c"),
  525.                             retr, timer_queued);
  526.                 break;
  527.  
  528.             case 1:
  529.                 sprintf(timers, NLS_CATGETS(catfd, netstatSet, netstat_on2,
  530.                                 "on (%2.2f/%ld) %c"),
  531.                     (double)time_len / 100, retr, timer_queued);
  532.                 break;
  533.  
  534.             default:
  535.                 sprintf(timers, NLS_CATGETS(catfd, netstatSet, netstat_unkn2,
  536.                                 "unkn-%d (%2.2f/%ld) %c"),
  537.                     timer_run, (double)time_len / 100,
  538.                     retr, timer_queued);
  539.                 break;
  540.         }
  541.         printf("udp   %6ld %6ld %-23s %-23s %-12s",
  542.             rxq, txq, local_addr, rem_addr, udp_state);
  543.  
  544.         if (flag_exp > 1)
  545.             printf("%-10s ", "");
  546.  
  547.         if (flag_opt) printf("%s", timers);
  548.         printf("\n");
  549.     }
  550.   }
  551.   return(0);
  552. }
  553.  
  554.  
  555. static int
  556. raw_info(void)
  557. {
  558.   char buffer[8192], local_addr[64], rem_addr[64];
  559.   char *raw_state, timer_queued, timers[64], more[512];
  560.   int num, local_port, rem_port, d, state, timer_run, lnr = 0;
  561.   struct sockaddr_in localaddr, remaddr;
  562.   struct aftype *ap;
  563.   unsigned long rxq, txq, time_len, retr;
  564.   
  565.   if ((procinfo = fopen(_PATH_PROCNET_RAW, "r")) == NULL) {
  566.     if (errno != ENOENT) {
  567.         perror(_PATH_PROCNET_RAW);
  568.         return(-1);
  569.     }
  570.     if (flag_arg || flag_ver)
  571.         ESYSNOT("netstat","AF INET (raw)");
  572.     if (flag_arg)
  573.         return(1);
  574.     else
  575.         return(0);
  576.   }
  577.  
  578.   fgets(buffer, sizeof(buffer), procinfo);
  579.   while (! feof(procinfo)) {
  580.     fgets(buffer, sizeof(buffer), procinfo);
  581.     if ((line[lnr] = (char *)malloc(strlen(buffer)+1)) != NULL) {
  582.         strcpy(line[lnr++], buffer);
  583.         if (flag_deb) fprintf(stderr, "%s", buffer);
  584.     }
  585.   }
  586.   (void) fclose(procinfo);
  587.   lnr--; lnr--;
  588.  
  589.   while (lnr >= 0) {
  590.     more[0] = '\0';
  591.     timer_queued = '\0';
  592.     num = sscanf(line[lnr--],
  593.         "%d: %lX:%X %lX:%X %X %lX:%lX %X:%lX %lX %c %s\n",
  594.         &d, (unsigned long*)&localaddr.sin_addr.s_addr, &local_port,
  595.         (unsigned long*)&remaddr.sin_addr.s_addr, &rem_port, &state,
  596.         &txq, &rxq, &timer_run, &time_len, &retr,
  597.         &timer_queued, more);
  598.         retr = 0L;
  599.     localaddr.sin_family = AF_INET;
  600.     remaddr.sin_family = AF_INET;
  601.     if ((ap = get_afntype(localaddr.sin_family)) == NULL) {
  602.         fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_netstat,
  603.                         "netstat: unsupported address family %d !\n"),
  604.             localaddr.sin_family);
  605.         continue;
  606.     }
  607.  
  608.     if (! flag_opt) more[0] = '\0';
  609.     if (flag_deb) fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_args, "%s -> %d args"), line[lnr+1], num);
  610.     if (num < 10) continue;
  611.  
  612.     raw_state = "";
  613.     strcpy(local_addr, ap->sprint((struct sockaddr *)&localaddr, flag_not));
  614.     strcpy(rem_addr, ap->sprint((struct sockaddr *)&remaddr, flag_not));
  615.     if (flag_all || localaddr.sin_addr.s_addr) {
  616.         sprintf(buffer, "%s", get_sname(htons(local_port), "raw", flag_not));
  617.         if ((strlen(local_addr) + strlen(buffer)) > 22) {
  618.             local_addr[22-strlen(buffer)] = '\0';
  619.         }
  620.         strcat(local_addr, ":");
  621.         strcat(local_addr, buffer);
  622.         sprintf(buffer, "%s", get_sname(htons(rem_port), "raw", flag_not));
  623.         if ((strlen(rem_addr) + strlen(buffer)) > 22) {
  624.             rem_addr[22-strlen(buffer)] = '\0';
  625.         }
  626.         strcat(rem_addr, ":");
  627.         strcat(rem_addr, buffer);
  628.  
  629.         timers[0] = '\0';
  630.         if (flag_opt) switch (timer_run) {
  631.             case 0:
  632.                 sprintf(timers, NLS_CATGETS(catfd, netstatSet, netstat_off3,
  633.                                 "off (0.00/%ld) %c"),
  634.                         retr, timer_queued);
  635.                 break;
  636.  
  637.             case 1:
  638.                 sprintf(timers, NLS_CATGETS(catfd, netstatSet, netstat_on3,
  639.                                 "on (%2.2f/%ld) %c"),
  640.                     (double)time_len / 100, retr,
  641.                     timer_queued);
  642.                 break;
  643.  
  644.             default:
  645.                 sprintf(timers, NLS_CATGETS(catfd, netstatSet, netstat_unkn3,
  646.                                 "unkn-%d (%2.2f/%ld) %c"),
  647.                     timer_run, (double)time_len / 100,
  648.                     retr, timer_queued);
  649.                 break;
  650.         }
  651.         printf("raw   %6ld %6ld %-23s %-23s %-12s",
  652.             rxq, txq, local_addr, rem_addr, raw_state);
  653.  
  654.         if (flag_exp > 1)
  655.             printf("%-10s ", "");
  656.  
  657.         if (flag_opt) printf("%s", timers);
  658.         printf("\n");
  659.     }
  660.   }
  661.   return(0);
  662. }
  663. #endif
  664.  
  665.  
  666. #if HAVE_AFUNIX
  667. static int
  668. unix_info(void)
  669. {
  670.   char buffer[8192], inode[MAXPATHLEN], path[MAXPATHLEN], ss_flags[32];
  671.   char *ss_proto, *ss_state, *ss_type;
  672.   int num, state, type, lnr = 0, has = 0;
  673.   void *d;
  674.   unsigned long refcnt, proto, flags;
  675. #define HAS_INODE 1
  676.   
  677.   if ((procinfo = fopen(_PATH_PROCNET_UNIX, "r")) == NULL) {
  678.     if (errno != ENOENT) {
  679.         perror(_PATH_PROCNET_UNIX);
  680.         return(-1);
  681.     }
  682.     if (flag_arg || flag_ver)
  683.         ESYSNOT("netstat","AF UNIX");
  684.     if (flag_arg)
  685.         return(1);
  686.     else
  687.         return(0);
  688.   }
  689.  
  690.   fgets(buffer, sizeof(buffer), procinfo);
  691.   
  692.   if (strstr(buffer,"Inode"))
  693.     has |= HAS_INODE;
  694.     
  695.   while (! feof(procinfo)) {
  696.     fgets(buffer, sizeof(buffer), procinfo);
  697.     if ((line[lnr] = (char *)malloc(strlen(buffer)+1)) != NULL) {
  698.         strcpy(line[lnr++], buffer);
  699.         if (flag_deb) fprintf(stderr, "%s", buffer);
  700.     }
  701.   }
  702.   (void) fclose(procinfo);
  703.   lnr--; lnr--;
  704.  
  705.   printf(NLS_CATGETS(catfd, netstatSet, netstat_unix, "Active UNIX domain sockets ")); /* xxx */
  706.   if (flag_all) printf(NLS_CATGETS(catfd, netstatSet, netstat_servers, "(including servers)")); /* xxx */
  707.            else printf(NLS_CATGETS(catfd, netstatSet, netstat_noservers, "(w/o servers)")); /* xxx */
  708.  
  709.   printf(NLS_CATGETS(catfd, netstatSet, netstat_header_unix,
  710.              "\nProto RefCnt Flags       Type       State         I-Node Path\n")); /* xxx */
  711.   while (lnr >= 0) {
  712.     path[0] = '\0';
  713.     inode[0] = '\0';
  714.     num = sscanf(line[lnr--], "%p: %lX %lX %lX %X %X %s %s",
  715.         &d, &refcnt, &proto, &flags, &type, &state, inode, path);
  716.     if (flag_deb) fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_args, "%s -> %d args"), line[lnr+1], num);
  717.     if (num < 6) continue;
  718.         if (!(has&HAS_INODE)) {
  719.           strcpy(path,inode);
  720.           strcpy(inode,"-");
  721.         }
  722.         if (!flag_all && (state == SS_UNCONNECTED) && (flags & SO_ACCEPTCON))
  723.             continue;
  724.             
  725.     switch(proto) {
  726.         case 0:
  727.             ss_proto = "unix";
  728.             break;
  729.  
  730.         default:
  731.             ss_proto = "??";
  732.     }
  733.  
  734.     switch(type) {
  735.         case SOCK_STREAM:
  736.             ss_type = "STREAM";
  737.             break;
  738.  
  739.         case SOCK_DGRAM:
  740.             ss_type = "DGRAM";
  741.             break;
  742.  
  743.         case SOCK_RAW:
  744.             ss_type = "RAW";
  745.             break;
  746.  
  747.         case SOCK_RDM:
  748.             ss_type = "RDM";
  749.             break;
  750.  
  751.         case SOCK_SEQPACKET:
  752.             ss_type = "SEQPACKET";
  753.             break;
  754.  
  755.         default:
  756.             ss_type = "UNKNOWN";
  757.     }
  758.  
  759.     switch(state) {
  760.         case SS_FREE:
  761.             ss_state = "FREE";
  762.             break;
  763.  
  764.         case SS_UNCONNECTED:
  765.             /*
  766.              * Unconnected sockets may be listening
  767.              * for something.
  768.              */
  769.             if (flags & SO_ACCEPTCON) {
  770.                 ss_state = "LISTENING";
  771.             } else {
  772.                 ss_state = "";
  773.             }
  774.             break;
  775.  
  776.         case SS_CONNECTING:
  777.             ss_state = "CONNECTING";
  778.             break;
  779.  
  780.         case SS_CONNECTED:
  781.             ss_state = "CONNECTED";
  782.             break;
  783.  
  784.         case SS_DISCONNECTING:
  785.             ss_state = "DISCONNECTING";
  786.             break;
  787.  
  788.         default:
  789.             ss_state = "UNKNOWN";
  790.     }
  791.  
  792.     strcpy(ss_flags, "[ ");
  793.     if (flags & SO_ACCEPTCON) strcat(ss_flags, "ACC ");
  794.     if (flags & SO_WAITDATA) strcat(ss_flags, "W ");
  795.     if (flags & SO_NOSPACE) strcat(ss_flags, "N ");
  796.     
  797.     strcat(ss_flags, "]");
  798.  
  799.     printf("%-5s %-6ld %-11s %-10s %-13s %-6s %s\n",
  800.         ss_proto, refcnt, ss_flags, ss_type, ss_state, inode, path);
  801.   }
  802.   return(0);
  803. }
  804. #endif
  805.  
  806.  
  807. #if HAVE_AFAX25
  808. static int ax25_info(void)
  809. {
  810.      FILE *f=fopen(_PATH_PROCNET_AX25, "r");
  811.     char buffer[256],dev[16];
  812.     int st,vs,vr,sendq,recvq;
  813.     static char *ax25_state[5]=
  814.      {
  815.         "LISTENING",
  816.          "SABM SENT",
  817.          "DISC SENT",
  818.         "ESTABLISHED",
  819.         "RECOVERY"
  820.      };
  821.     if(!(f=fopen(_PATH_PROCNET_AX25, "r")))
  822.     {
  823.         if (errno != ENOENT) {
  824.             perror(_PATH_PROCNET_AX25);
  825.             return(-1);
  826.         }
  827.         if (flag_arg || flag_ver)
  828.             ESYSNOT("netstat","AF AX25");
  829.         if (flag_arg)
  830.             return(1);
  831.         else
  832.             return(0);
  833.       }
  834.     printf(NLS_CATGETS(catfd, netstatSet, netstat_ax25, "Activate AX.25 sockets\n"));
  835.     printf(NLS_CATGETS(catfd, netstatSet, netstat_header_ax25, "Dest       Source     Device  State        Vr/Vs  Send-Q  Recv-Q\n"));
  836.      fgets(buffer,256,f);
  837.      while(fgets(buffer,256,f))
  838.      {
  839.          buffer[9]=0;
  840.         buffer[19]=0;
  841.         sscanf(buffer+20,"%s %d %d %d %*d %*d/%*d %*d/%*d %*d/%*d %*d/%*d %*d %*d %d %d",
  842.             dev,&st,&vs,&vr,&sendq,&recvq);
  843.         printf("%-9s  %-9s  %-6s  %-11s  %02d/%02d  %-6d  %-6d\n",
  844.              buffer,buffer+10,
  845.             dev,
  846.              ax25_state[st],
  847.             vr,vs,sendq,recvq);
  848.      }
  849.      fclose(f);
  850.      return 0;        
  851. }
  852. #endif
  853.  
  854.  
  855. #if HAVE_AFIPX
  856. static int ipx_info(void)
  857. {
  858.     FILE *f;
  859.     char buf[256];
  860.     unsigned long txq,rxq;
  861.     unsigned int state;
  862.     unsigned int uid;
  863.     char *st;
  864.     int nc;
  865.     struct aftype *ap;
  866.     struct passwd *pw;
  867.     char sad[50],dad[50];
  868.     struct sockaddr sa;
  869.     unsigned sport=0,dport=0;
  870.             
  871.     if(!(f=fopen(_PATH_PROCNET_IPX,"r")))
  872.     {
  873.         if (errno != ENOENT) {
  874.             perror(_PATH_PROCNET_IPX);
  875.             return(-1);
  876.         }
  877.         if (flag_arg || flag_ver)
  878.             ESYSNOT("netstat","AF IPX");
  879.         if (flag_arg)
  880.             return(1);
  881.         else
  882.             return(0);
  883.       }
  884.     printf(NLS_CATGETS(catfd, netstatSet, netstat_header_ipx,
  885.            "Active IPX sockets\nProto Recv-Q Send-Q Local Address              Foreign Address            State")); /* xxx */
  886.     if (flag_exp>1)
  887.         printf(NLS_CATGETS(catfd, netstatSet, netstat_header_ipx2,
  888.             " User")); /* xxx */
  889.     printf("\n");
  890.     if ((ap = get_afntype(AF_IPX)) == NULL) {
  891.         EINTERN("netstat.c","AF_IPX missing");
  892.         return(-1);
  893.       }
  894.  
  895.     fgets(buf,255,f);
  896.     
  897.     while(fgets(buf,255,f)!=NULL)
  898.     {
  899.         sscanf(buf, "%s %s %lX %lX %d %d",
  900.             sad,dad,&txq,&rxq,&state,&uid);
  901.         if ((st = rindex(sad,':'))) {
  902.             *st++ = '\0';
  903.             sscanf(st,"%X",&sport); /* net byt order */
  904.             sport = ntohs(sport);
  905.         } else {
  906.             EINTERN("netstat.c",_PATH_PROCNET_IPX" sport format error");
  907.             return(-1);
  908.         }
  909.         nc = 0;
  910.         if (strcmp(dad,"Not_Connected")!=0) {
  911.             if ((st = rindex(dad,':'))) {
  912.                 *st++ = '\0';
  913.                 sscanf(st,"%X",&dport); /* net byt order */
  914.                 dport = ntohs(dport);
  915.             } else {
  916.                 EINTERN("netstat.c",_PATH_PROCNET_IPX" dport format error");
  917.                 return(-1);
  918.             }
  919.         } else
  920.             nc = 1;
  921.             
  922.         switch(state)
  923.         {
  924.             case TCP_ESTABLISHED:
  925.                 st = "ESTAB";
  926.                 break;
  927.  
  928.             case TCP_CLOSE:
  929.                 st = "";
  930.                 break;
  931.  
  932.             default:
  933.                 st = "UNK.";
  934.                 break;
  935.         }
  936.  
  937.         /* Fetch and resolve the Source */
  938.         (void)ap->input(4,sad,&sa);
  939.         strcpy(buf, ap->sprint(&sa, flag_not));
  940.         sprintf(sad,"%s:%04X",buf,sport);
  941.  
  942.         if (!nc) {
  943.             /* Fetch and resolve the Destination */
  944.             (void)ap->input(4,dad,&sa);
  945.             strcpy(buf, ap->sprint(&sa, flag_not));
  946.             sprintf(dad,"%s:%04X",buf,dport);
  947.         } else strcpy(dad,"-");
  948.  
  949.         printf("IPX   %6ld %6ld %-26s %-26s %-5s", txq, rxq, sad, dad, st);
  950.         if (flag_exp>1) {
  951.             if (!flag_not && ((pw = getpwuid(uid)) != NULL))
  952.                 printf(" %-10s", pw->pw_name);
  953.             else
  954.                 printf(" %-10d",uid);
  955.         }
  956.         printf("\n");
  957.     }
  958.     fclose(f);
  959.     return 0;
  960. }    
  961. #endif
  962.  
  963. static void
  964. ife_print(struct interface *ptr)
  965. {
  966.   printf("%-5.5s ", ptr->name);
  967.   printf("%5d %3d ", ptr->mtu, ptr->metric);
  968.   /* If needed, display the interface statistics. */
  969.   printf("%6u %6u %6u %6u ",
  970.      ptr->stats.rx_packets, ptr->stats.rx_errors,
  971.      ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors);
  972.   printf("%6u %6u %6u %6u ",
  973.      ptr->stats.tx_packets, ptr->stats.tx_errors,
  974.      ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors);
  975.   if (ptr->flags == 0) printf(NLS_CATGETS(catfd, netstatSet, netstat_noflags, "[NO FLAGS]"));
  976.   if (ptr->flags & IFF_ALLMULTI) printf("A");
  977.   if (ptr->flags & IFF_BROADCAST) printf("B");
  978.   if (ptr->flags & IFF_DEBUG) printf("D");
  979.   if (ptr->flags & IFF_LOOPBACK) printf("L");
  980.   if (ptr->flags & IFF_PROMISC) printf("M");
  981.   if (ptr->flags & IFF_NOTRAILERS) printf("N");
  982.   if (ptr->flags & IFF_NOARP) printf("O");
  983.   if (ptr->flags & IFF_POINTOPOINT) printf("P");
  984.   if (ptr->flags & IFF_RUNNING) printf("R");
  985.   if (ptr->flags & IFF_UP) printf("U");
  986.   printf("\n");
  987. }
  988.  
  989. static void if_getstats(char *ifname, struct interface *ife)
  990. {
  991.   FILE *f=fopen("/proc/net/dev","r");
  992.   char buf[256];
  993.   char *bp;
  994.   if(f==NULL)
  995.       return;
  996.   while(fgets(buf,255,f))
  997.   {
  998.       bp=buf;
  999.       while(*bp&&isspace(*bp))
  1000.           bp++;
  1001.       if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
  1002.       {
  1003.          bp=strchr(bp,':');
  1004.          bp++;
  1005.          sscanf(bp,"%d %d %d %d %d %d %d %d %d %d %d",
  1006.              &ife->stats.rx_packets,
  1007.              &ife->stats.rx_errors,
  1008.              &ife->stats.rx_dropped,
  1009.              &ife->stats.rx_fifo_errors,
  1010.              &ife->stats.rx_frame_errors,
  1011.              
  1012.              &ife->stats.tx_packets,
  1013.              &ife->stats.tx_errors,
  1014.              &ife->stats.tx_dropped,
  1015.              &ife->stats.tx_fifo_errors,
  1016.              &ife->stats.collisions,
  1017.              
  1018.              &ife->stats.tx_carrier_errors
  1019.          );
  1020.          fclose(f);
  1021.          return;
  1022.       }
  1023.   }
  1024.   fclose(f);
  1025. }
  1026.   
  1027. /* Fetch the inteface configuration from the kernel. */
  1028. static int
  1029. if_fetch(char *ifname, struct interface *ife)
  1030. {
  1031.   struct ifreq ifr;
  1032.   
  1033.   memset((char *) ife, 0, sizeof(struct interface));
  1034.   strcpy(ife->name, ifname);
  1035.   
  1036.   strcpy(ifr.ifr_name, ifname);
  1037.   if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {
  1038.     fprintf(stderr, "SIOCGIFFLAGS: %s\n", strerror(errno));
  1039.     return(-1);
  1040.   }
  1041.   ife->flags = ifr.ifr_flags;
  1042.   
  1043.   strcpy(ifr.ifr_name, ifname);
  1044.   if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0) {
  1045.     memset(&ife->addr, 0, sizeof(struct sockaddr));
  1046.   } else ife->addr = ifr.ifr_addr;
  1047.   
  1048.   strcpy(ifr.ifr_name, ifname);
  1049.   if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) {
  1050.     memset(&ife->hwaddr, 0, sizeof(struct sockaddr));
  1051.   } else ife->hwaddr = ifr.ifr_addr;
  1052.   
  1053.   strcpy(ifr.ifr_name, ifname);
  1054.   if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) {
  1055.     ife->metric = 0;
  1056.   } else ife->metric = ifr.ifr_metric;
  1057.   
  1058.   strcpy(ifr.ifr_name, ifname);
  1059.   if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0) {
  1060.     ife->mtu = 0;
  1061.   } else ife->mtu = ifr.ifr_mtu;
  1062.   
  1063.   strcpy(ifr.ifr_name, ifname);
  1064.   if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) < 0) {
  1065.     memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
  1066.   } else ife->dstaddr = ifr.ifr_dstaddr;
  1067.   
  1068.   strcpy(ifr.ifr_name, ifname);
  1069.   if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0) {
  1070.     memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
  1071.   } else ife->broadaddr = ifr.ifr_broadaddr;
  1072.   
  1073.   strcpy(ifr.ifr_name, ifname);
  1074.   if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) {
  1075.     memset(&ife->netmask, 0, sizeof(struct sockaddr));
  1076.   } else {
  1077.     memcpy(ife->netmask.sa_data, &ifr.ifr_data, sizeof(struct sockaddr));
  1078.   }
  1079.     
  1080.   if_getstats(ifname,ife);
  1081. /*  strcpy(ifr.ifr_name, ifname);
  1082.   ifr.ifr_data = (caddr_t) &ife->stats;
  1083.   if (ioctl(skfd, SIOCGIFSTATS, &ifr) < 0) {
  1084.     memset(&ife->stats, 0, sizeof(struct dev_stats));
  1085.   }
  1086.   */
  1087.   return(0);
  1088. }
  1089.  
  1090.  
  1091. static int
  1092. iface_info(void)
  1093. {
  1094.   char buff[1024];
  1095.   struct interface ife;
  1096.   struct ifconf ifc;
  1097.   struct ifreq *ifr;
  1098.   int i;
  1099.   
  1100.   /* Create a channel to the NET kernel. */
  1101.   if ((skfd = socket(AF_INET,SOCK_DGRAM,0)) < 0) {
  1102.     perror("socket");
  1103.     return(E_READ);
  1104.   }
  1105.   
  1106.   ifc.ifc_len = sizeof(buff);
  1107.   ifc.ifc_buf = buff;
  1108.   if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
  1109.     perror("SIOCGIFCONF");
  1110.     close(skfd);
  1111.     return(E_IOCTL);
  1112.   }
  1113.  
  1114.   printf(NLS_CATGETS(catfd, netstatSet, netstat_interface, "Kernel Interface table\n"));
  1115.   printf(NLS_CATGETS(catfd, netstatSet, netstat_header_iface,
  1116.              "Iface   MTU Met  RX-OK RX-ERR RX-DRP RX-OVR  TX-OK TX-ERR TX-DRP TX-OVR Flags\n"));
  1117.   
  1118.   ifr = ifc.ifc_req;
  1119.   for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
  1120.     if (if_fetch(ifr->ifr_name, &ife) < 0) {
  1121.         fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_unkn_iface,
  1122.                         "%s: unknown interface.\n"), ifr->ifr_name);
  1123.     }
  1124.     
  1125.     if (((ife.flags & IFF_UP) == 0) && !flag_all) continue;
  1126.     ife_print(&ife);
  1127.   }
  1128.   close(skfd);
  1129.   return(0);
  1130. }
  1131.  
  1132.  
  1133. static void
  1134. version(void) 
  1135. {
  1136.     printf("%s\n%s\n%s\n%s\n", Release, Version, Signature, Features);
  1137.     NLS_CATCLOSE(catfd)
  1138.     exit(1);
  1139. }
  1140.  
  1141.  
  1142. static void
  1143. usage(void)
  1144. {
  1145.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage1,  "usage: netstat [-veenNcCF] [<Af>] -r         netstat {-V|--version|-h|--help}\n"));
  1146.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage2,  "       netstat [-vnNcaeo] [<Socket>]\n"));
  1147.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage3,  "       netstat { [-veenNac] -i | [-vnNc] -L | [-cnNe] -M }\n\n"));
  1148.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage4,  "        -r, --route              display routing table\n")); /* xxx */
  1149.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage5,  "        -L, --netlink            display netlink kernel messages\n"));
  1150.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage6,  "        -i, --interfaces         display interface table\n"));
  1151.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage7,  "        -M, --masquerade         display masqueraded connections\n\n"));
  1152.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage8,  "        -v, --verbose            be verbose\n"));
  1153.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage9,  "        -n, --numeric            dont resolve names\n"));
  1154.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage10, "        -e, --extend             display other/more informations\n"));
  1155.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage11, "        -c, --continuous         continuous listing\n\n"));
  1156.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage12, "        -a, --all, --listening   display all\n"));
  1157.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage13, "        -o, --timers             display timers\n\n"));
  1158.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage14, "<Socket>={-t|--tcp} {-u|--udp} {-w|--raw} {-x|--unix} --ax25 --ipx --netrom\n"));
  1159.   fprintf(stderr, NLS_CATGETS(catfd, netstatSet, netstat_usage15, "<Af>= -A {inet|ipx|netrom|ddp|ax25},... --inet --ipx --netrom --ddp --ax25\n"));
  1160.   NLS_CATCLOSE(catfd)
  1161.   exit(1);
  1162. }
  1163.  
  1164.  
  1165. int main
  1166. (int argc, char *argv[])
  1167. {
  1168.   int i;
  1169.   int lop;
  1170.   struct option longopts[]=
  1171.   {
  1172.     AFTRANS_OPTS,
  1173.       {"version",    0,    0,    'V'},
  1174.       {"interfaces",    0,    0,    'i'},
  1175.       {"help",    0,    0,    'h'},
  1176.       {"route",    0,    0,    'r'},
  1177.       {"netlink",    2,    0,    'L'},
  1178.       {"masquerade",    0,    0,    'M'},
  1179.       {"protocol",    1,    0,    'A'},
  1180.       {"tcp",        0,    0,    't'},
  1181.       {"udp",        0,    0,    'u'},
  1182.       {"raw",        0,    0,    'w'},
  1183.       {"unix",    0,    0,    'x'},
  1184.       {"listening",    0,    0,    'a'},
  1185.       {"all",        0,    0,    'a'},
  1186.       {"timers",    0,    0,    'o'},
  1187.       {"continuous",    0,    0,    'c'},
  1188.       {"extend",    0,    0,    'e'},
  1189.       {"verbose",    0,    0,    'v'},
  1190.       {"numeric",    0,    0,    'n'},
  1191.       {"symbolic",    0,    0,    'N'},
  1192.     {"cache",    0,    0,    'C'},
  1193.     {"fib",        0,    0,    'F'},
  1194.       {NULL,        0,    0,    0}
  1195.   };
  1196.   
  1197. #if NLS
  1198.   setlocale (LC_MESSAGES, "");
  1199.   catfd = catopen ("nettools", MCLoadBySet);
  1200. #endif
  1201.  
  1202.   getroute_init();             /* Set up AF routing support */
  1203.  
  1204.   afname[0]='\0';
  1205.   while ((i = getopt_long(argc, argv, "MLCFA:acdehinNortuVv?wx", longopts, &lop)) != EOF) switch(i) {
  1206.       case -1:
  1207.           break;
  1208.       case 1:
  1209.         if (lop < 0 || lop >= AFTRANS_CNT) {
  1210.             EINTERN("netstat.c","longopts 1 range");
  1211.             break;
  1212.         }
  1213.         if (aftrans_opt(longopts[lop].name)) {
  1214.             NLS_CATCLOSE(catfd)
  1215.             exit(1);
  1216.         }
  1217.         break;
  1218.     case 'A':
  1219.         if (aftrans_opt(optarg)) {
  1220.             NLS_CATCLOSE(catfd)
  1221.             exit(1);
  1222.         }
  1223.         break;
  1224.     case 'L':
  1225.         flag_nlp++;
  1226.         break;
  1227.     case 'M':
  1228.         flag_mas++;
  1229.         break;
  1230.     case 'a':
  1231.         flag_all++;
  1232.         break;
  1233.     case 'c':
  1234.         flag_cnt++;
  1235.         break;
  1236.  
  1237.     case 'd':
  1238.         flag_deb++;
  1239.         break;
  1240.     case 'e':
  1241.         flag_exp++;
  1242.         break;
  1243.     case 'i':
  1244.         flag_int++;
  1245.         break;
  1246.  
  1247.     case 'n':
  1248.         flag_not|=FLAG_NUM;
  1249.         break;
  1250.     case 'N':
  1251.         flag_not|=FLAG_SYM;
  1252.         break;
  1253.     case 'C':
  1254.         flag_cf|=FLAG_CACHE;
  1255.         break;
  1256.     case 'F':
  1257.         flag_cf|=FLAG_FIB;
  1258.         break;
  1259.     case 'o':
  1260.         flag_opt++;
  1261.         break;
  1262.     case 'V':
  1263.         version();
  1264.         /*NOTREACHED*/
  1265.     case 'v':
  1266.         flag_ver|=FLAG_VERBOSE;
  1267.         break;
  1268.     case 'r':
  1269.         flag_rou++;
  1270.         break;
  1271.  
  1272.     case 't':
  1273.         flag_tcp++;
  1274.         break;
  1275.  
  1276.     case 'u':
  1277.         flag_udp++;
  1278.         break;
  1279.     case 'w':
  1280.         flag_raw++;
  1281.         break;
  1282.     case 'x':
  1283.         if (aftrans_opt("unix")) {
  1284.             NLS_CATCLOSE(catfd)
  1285.             exit(1);
  1286.         }
  1287.         break;
  1288.     case '?':
  1289.     case 'h':
  1290.         usage();
  1291.   }
  1292.   
  1293.   if (flag_int + flag_rou + flag_nlp + flag_mas > 1)
  1294.       usage();
  1295.   
  1296.   if (flag_inet)
  1297.       flag_tcp = flag_udp = flag_raw = 1;
  1298.       
  1299.   flag_arg = flag_tcp + flag_udp + flag_raw + flag_unx + flag_ipx 
  1300.            + flag_ax25 + flag_netrom;
  1301.            
  1302.   if (flag_nlp) {
  1303. #if HAVE_RT_NETLINK
  1304.     i=netlink_print();
  1305. #else
  1306.     ENOSUPP("netstat.c","RT_NETLINK");
  1307.     i=-1;
  1308. #endif    
  1309.     NLS_CATCLOSE(catfd)
  1310.     return(i);
  1311.   }
  1312.   if (flag_mas) {
  1313. #if HAVE_FW_MASQUERADE
  1314. #if MORE_THAN_ONE_MASQ_AF
  1315.       if (!afname[0])
  1316.           strcpy(afname,DFLT_AF);
  1317. #endif  
  1318.       for(;;) {
  1319.           i = ip_masq_info(flag_not, flag_exp);
  1320.          if (i || !flag_cnt) break;
  1321.         sleep(1);
  1322.     }
  1323. #else
  1324.     ENOSUPP("netstat.c","FW_MASQUERADE");
  1325.     i=-1;
  1326. #endif
  1327.     NLS_CATCLOSE(catfd)
  1328.     return(i);
  1329.   }
  1330.   if (flag_rou) {
  1331.     int options=0;
  1332.         
  1333.       if (!afname[0])
  1334.           strcpy(afname,DFLT_AF);
  1335.  
  1336.       if (flag_exp == 2)
  1337.           flag_exp = 1;
  1338.       else if (flag_exp == 1)
  1339.           flag_exp = 2;
  1340.           
  1341.     options = (flag_exp & FLAG_EXT) | flag_not | flag_cf | flag_ver ;
  1342.     if (!flag_cf)
  1343.         options |= FLAG_FIB;
  1344.  
  1345.       for(;;) {
  1346.           i = route_info(afname,options);
  1347.          if (i || !flag_cnt) break;
  1348.         sleep(1);
  1349.     }
  1350.     NLS_CATCLOSE(catfd)
  1351.     return(i);
  1352.   }
  1353.   
  1354.   if (flag_int) {
  1355.     for (;;) {
  1356.         i = iface_info();
  1357.         if (!flag_cnt || i) break;
  1358.         sleep(1);
  1359.       }
  1360.     NLS_CATCLOSE(catfd)
  1361.     return(i);
  1362.   }
  1363.  
  1364.   for (;;) {
  1365.       if (!flag_arg || flag_tcp || flag_udp || flag_raw) {
  1366.   #if HAVE_AFINET
  1367.         printf(NLS_CATGETS(catfd, netstatSet, netstat_internet, "Active Internet connections ")); /* xxx */
  1368.         if (flag_all) printf(NLS_CATGETS(catfd, netstatSet, netstat_servers, "(including servers)")); /* xxx */
  1369.                  else printf(NLS_CATGETS(catfd, netstatSet, netstat_noservers, "(w/o servers)")); /* xxx */
  1370.  
  1371.         printf(NLS_CATGETS(catfd, netstatSet, netstat_header_internet,
  1372.                "\nProto Recv-Q Send-Q Local Address           Foreign Address         State      ")); /* xxx */
  1373.         if (flag_exp > 1)
  1374.             printf(NLS_CATGETS(catfd, netstatSet, netstat_header_internet2,
  1375.                " User      ")); /* xxx */
  1376.         if (flag_opt)
  1377.             printf(NLS_CATGETS(catfd, netstatSet, netstat_header_internet3,
  1378.                " Timer")); /* xxx */
  1379.         printf("\n");
  1380. #else
  1381.         if (flag_arg)
  1382.             { i=1; ENOSUPP("netstat","AF INET"); }
  1383. #endif
  1384.     }
  1385. #if HAVE_AFINET
  1386.     if (!flag_arg || flag_tcp) {
  1387.         i = tcp_info();
  1388.         if (i) {  NLS_CATCLOSE(catfd)  return(i); }
  1389.     }
  1390.  
  1391.     if (!flag_arg || flag_udp) {
  1392.         i = udp_info();
  1393.         if (i) {  NLS_CATCLOSE(catfd)  return(i); }
  1394.     }
  1395.  
  1396.     if (!flag_arg || flag_raw) {
  1397.         i = raw_info();
  1398.         if (i) {  NLS_CATCLOSE(catfd)  return(i); }
  1399.     }
  1400. #endif
  1401.  
  1402.     if (!flag_arg || flag_unx) {
  1403. #if HAVE_AFUNIX
  1404.         i = unix_info();
  1405.         if (i) {  NLS_CATCLOSE(catfd)  return(i); }
  1406. #else
  1407.         if (flag_arg)
  1408.             { i=1; ENOSUPP("netstat","AF UNIX"); }
  1409. #endif
  1410.     }
  1411.  
  1412.     if(!flag_arg || flag_ipx) {
  1413. #if HAVE_AFIPX
  1414.         i = ipx_info();
  1415.         if(i) {  NLS_CATCLOSE(catfd)  return(i); }
  1416. #else
  1417.         if (flag_arg)
  1418.             { i=1; ENOSUPP("netstat","AF IPX"); }
  1419. #endif
  1420.     }
  1421.  
  1422.     if(!flag_arg || flag_ax25) {
  1423. #if HAVE_AFAX25
  1424.         i = ax25_info();
  1425.         if(i) {  NLS_CATCLOSE(catfd)  return(i); }
  1426. #else
  1427.         if (flag_arg)
  1428.             { i=1; ENOSUPP("netstat","AF AX25"); }
  1429. #endif
  1430.     }
  1431.  
  1432.     if(!flag_arg || flag_netrom) {
  1433. #if HAVE_AFNETROM
  1434.         i = netrom_info();
  1435.         if(i) {  NLS_CATCLOSE(catfd)  return(i); }
  1436. #else
  1437.         if (flag_arg)
  1438.             { i=1; ENOSUPP("netstat","AF NETROM"); }
  1439. #endif
  1440.     }
  1441.     
  1442.     if (!flag_cnt || i) break;
  1443.     sleep(1);
  1444.   }
  1445.  
  1446.   NLS_CATCLOSE(catfd)
  1447.   return(i);
  1448. }
  1449.